package com.xyazm.order.service.impl;

import com.xyazm.common.enums.*;
import com.xyazm.common.utils.RandomUtil;
import com.xyazm.fulfill.domain.param.CancelFulfillParam;
import com.xyazm.order.dao.*;
import com.xyazm.order.domain.dto.CancelOrderAssembleDTO;
import com.xyazm.order.domain.dto.OrderInfoDTO;
import com.xyazm.order.domain.dto.OrderItemDTO;
import com.xyazm.order.domain.entity.*;
import com.xyazm.order.domain.param.CancelOrderAssembleParam;
import com.xyazm.order.enums.*;
import com.xyazm.order.mapstruct.OrderApiMapstruct;
import com.xyazm.order.remote.FulfillRemote;
import com.xyazm.order.service.ICancelOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author xuyou
 * @date 2022年07月24日 13:01
 */
@Slf4j
@Service
public class CancelOrderServiceImpl implements ICancelOrderService {


    @Autowired
    private FulfillRemote fulfillRemote;

    @Autowired
    private OrderInfoDAO orderInfoDAO;
    @Autowired
    private AfterSaleInfoDAO afterSaleInfoDAO;
    @Autowired
    private AfterSaleItemDAO afterSaleItemDAO;
    @Autowired
    private AfterSaleLogDAO afterSaleLogDAO;
    @Autowired
    private OrderPaymentDetailDAO orderPaymentDetailDAO;
    @Autowired
    private AfterSaleRefundDAO afterSaleRefundDAO;
    @Autowired
    private OrderOperateLogDAO orderOperateLogDAO;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void cancelOrderFulfillmentAndUpdateOrderStatus(CancelOrderAssembleDTO cancelOrderAssembleDTO) {
        // 取消履约
        cancelFulfill(cancelOrderAssembleDTO);
        // 更新订单状态和记录订单操作日志
        updateOrderStatusAndSaveOperationLog(cancelOrderAssembleDTO);
    }

    /**
     * 取消订单操作 记录售后信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertCancelOrderAfterSale(CancelOrderAssembleParam cancelOrderAssembleParam, Integer afterSaleStatus) {

        // 1.新增售后订单表
        String afterSaleId = cancelOrderAssembleParam.getAfterSaleId();
        String orderId = cancelOrderAssembleParam.getOrderId();
        OrderInfoDO orderInfoDO = orderInfoDAO.getByOrderId(orderId);
        AfterSaleInfoDO afterSaleInfoDO = this.insertAfterSaleInfoTable(orderInfoDO, afterSaleId);

        // 2.新增售后订单明细表
        List<OrderItemDTO> orderItemDTOList = cancelOrderAssembleParam.getOrderItemDTOList();
        this.insertAfterSaleItemTable(afterSaleId,orderId,orderItemDTOList);

        // 3.新增售后变更日志表
        OrderInfoDTO orderInfoDTO = cancelOrderAssembleParam.getOrderInfoDTO();
        this.insertAfterSaleLogTable(afterSaleId,orderInfoDTO, AfterSaleStatusEnum.UN_CREATED.getCode(), afterSaleStatus);

        // 4.新增售后退款单表
        this.insertAfterSaleRefundTable(afterSaleId, orderInfoDTO, afterSaleInfoDO.getRealRefundAmount());

    }


    /**
     * 取消履约
     * @author xuyou
     * 2022/7/24 0024 13:08
    */
    private void cancelFulfill(CancelOrderAssembleDTO cancelOrderAssembleDTO) {
        OrderInfoDTO orderInfoDTO = cancelOrderAssembleDTO.getOrderInfoDTO();
        if (OrderStatusEnum.CREATED.getCode().equals(orderInfoDTO.getOrderStatus())) {
            log.warn("订单状态为已创建,不需取消履约");
            return;
        }
        CancelFulfillParam cancelFulfillParam = OrderApiMapstruct.INSTANCE.convertCancelFulfillParam(orderInfoDTO);
        // 调用履约服务api-履约通知停止配送
        fulfillRemote.cancelFulfill(cancelFulfillParam);
    }


    /**
     * 更新订单状态和记录订单操作日志
     * @author xuyou
     * 2022/7/24 0024 13:17
     * @param cancelOrderAssembleDTO
     */
    private void updateOrderStatusAndSaveOperationLog(CancelOrderAssembleDTO cancelOrderAssembleDTO) {
        Integer cancelType = cancelOrderAssembleDTO.getCancelType();
        // 更新订单状态
        OrderInfoDTO orderInfoDTO = cancelOrderAssembleDTO.getOrderInfoDTO();
        OrderInfoDO orderInfoDO = OrderApiMapstruct.INSTANCE.convertOrderInfo(orderInfoDTO);
        // 订单取消类型 0-手动取消 1-超时未支付
        orderInfoDO.setCancelType(cancelType);
        orderInfoDO.setOrderStatus(OrderStatusEnum.CANCELLED.getCode());
        orderInfoDO.setCancelTime(new Date());
        orderInfoDAO.updateOrderInfo(orderInfoDO);
        log.info("更新订单信息OrderInfo状态: orderId:{},status:{}",
                orderInfoDO.getOrderId(), orderInfoDO.getOrderStatus());

        // 添加订单操作日志
        OrderOperateLogDO orderOperateLogDO = new OrderOperateLogDO();
        orderOperateLogDO.setOrderId(cancelOrderAssembleDTO.getOrderId());
        // 前置状态
        orderOperateLogDO.setPreStatus(orderInfoDTO.getOrderStatus());
        // 当前状态- 已取消
        orderOperateLogDO.setCurrentStatus(OrderStatusEnum.CANCELLED.getCode());

        // 用户手动取消
        if (OrderCancelTypeEnum.USER_CANCELED.getCode().equals(cancelType)) {
            orderOperateLogDO.setOperateType(OrderOperateTypeEnum.MANUAL_CANCEL_ORDER.getCode());
            orderOperateLogDO.setRemark(OrderOperateTypeEnum.MANUAL_CANCEL_ORDER.getMsg()
                    + orderOperateLogDO.getPreStatus() + "-" + orderOperateLogDO.getCurrentStatus());
        }
        if (OrderCancelTypeEnum.TIMEOUT_CANCELED.getCode().equals(cancelType)) {
            // 超时未支付自动取消订单
            orderOperateLogDO.setOperateType(OrderOperateTypeEnum.AUTO_CANCEL_ORDER.getCode());
            orderOperateLogDO.setRemark(OrderOperateTypeEnum.AUTO_CANCEL_ORDER.getMsg()
                    + orderOperateLogDO.getPreStatus() + "-" + orderOperateLogDO.getCurrentStatus());
        }
        orderOperateLogDAO.save(orderOperateLogDO);
        log.info("新增订单操作日志OrderOperateLog状态,orderId:{}, PreStatus:{},CurrentStatus:{}",
                orderOperateLogDO.getOrderId(),
                orderOperateLogDO.getPreStatus(),
                orderOperateLogDO.getCurrentStatus());
    }






    /**
     * 新增售后订单表
     * @author xuyou
     * @date: 2022/6/29 14:26
     */
    private AfterSaleInfoDO insertAfterSaleInfoTable(OrderInfoDO orderInfoDO, String afterSaleId) {
        AfterSaleInfoDO afterSaleInfoDO = new AfterSaleInfoDO();
        // 售后订单号
        afterSaleInfoDO.setAfterSaleId(afterSaleId);
        afterSaleInfoDO.setOrderId(orderInfoDO.getOrderId());
        afterSaleInfoDO.setUserId(orderInfoDO.getUserId());
        // 取消订单过程中的 申请退款金额 和 实际退款金额 都是实付退款金额 金额相同
        afterSaleInfoDO.setApplyRefundAmount(orderInfoDO.getPayAmount());
        afterSaleInfoDO.setRealRefundAmount(orderInfoDO.getPayAmount());
        // 接入方业务标识 - 自营商城
        afterSaleInfoDO.setBusinessIdentifier(BusinessIdentifierEnum.SELF_MALL.getCode());
        // 订单来源渠道 - 自营商城
        afterSaleInfoDO.setOrderSourceChannel(BusinessIdentifierEnum.SELF_MALL.getCode());
        // 订单类型 - 一般订单
        afterSaleInfoDO.setOrderType(OrderTypeEnum.NORMAL.getCode());
        // 售后单状态 - 审核通过
        afterSaleInfoDO.setAfterSaleStatus(AfterSaleStatusEnum.REVIEW_ACCEPT.getCode());
        // 取消订单 - 整笔退款
        afterSaleInfoDO.setAfterSaleType(AfterSaleTypeEnum.RETURN_MONEY.getCode());
        // 订单取消类型
        Integer cancelType = orderInfoDO.getCancelType();
        if (OrderCancelTypeEnum.TIMEOUT_CANCELED.getCode().equals(cancelType)) {
            afterSaleInfoDO.setAfterSaleTypeDetail(AfterSaleTypeDetailEnum.TIMEOUT_NO_PAY.getCode());
            afterSaleInfoDO.setRemark("超时未支付自动取消");
        } else if (OrderCancelTypeEnum.USER_CANCELED.getCode().equals(cancelType)) {
            afterSaleInfoDO.setAfterSaleTypeDetail(AfterSaleTypeDetailEnum.USER_CANCEL.getCode());
            afterSaleInfoDO.setRemark("用户手动取消");
        }
        // 申请原因编码 - 取消订单
        afterSaleInfoDO.setApplyReasonCode(AfterSaleReasonEnum.CANCEL.getCode());
        afterSaleInfoDO.setApplyReason(AfterSaleReasonEnum.CANCEL.getMsg());
        // 申请售后来源 - 系统自动退款
        afterSaleInfoDO.setApplySource(AfterSaleApplySourceEnum.SYSTEM.getCode());
        Date date = new Date();
        afterSaleInfoDO.setApplyTime(date);
        afterSaleInfoDO.setReviewTime(date);
        afterSaleInfoDAO.save(afterSaleInfoDO);
        log.info("新增订单售后记录,订单号:{},售后单号:{},订单售后状态:{}", afterSaleInfoDO.getOrderId(),
                afterSaleInfoDO.getAfterSaleId(), afterSaleInfoDO.getAfterSaleStatus());
        return afterSaleInfoDO;
    }


    /**
     * 新增售后订单明细表
     * @author xuyou
     * @date: 2022/6/29 14:37
     */
    private void insertAfterSaleItemTable(String afterSaleId, String orderId, List<OrderItemDTO> orderItemDTOList) {
        List<AfterSaleItemDO> itemDOList = new ArrayList<>(orderItemDTOList.size());
        for (OrderItemDTO orderItem : orderItemDTOList) {
            AfterSaleItemDO afterSaleItemDO = new AfterSaleItemDO();
            afterSaleItemDO.setAfterSaleId(afterSaleId);
            afterSaleItemDO.setOrderId(orderId);
            afterSaleItemDO.setSkuCode(orderItem.getSkuCode());
            afterSaleItemDO.setProductName(orderItem.getProductName());
            afterSaleItemDO.setProductImg(orderItem.getProductImg());
            afterSaleItemDO.setReturnQuantity(orderItem.getSaleQuantity());
            afterSaleItemDO.setOriginAmount(orderItem.getOriginAmount());
            afterSaleItemDO.setApplyRefundAmount(orderItem.getOriginAmount());
            afterSaleItemDO.setRealRefundAmount(orderItem.getPayAmount());
            itemDOList.add(afterSaleItemDO);
        }
        afterSaleItemDAO.saveBatch(itemDOList);
    }

    /**
     * 新增售后变更日志表
     * @author xuyou
     * @date: 2022/6/29 14:55
     */
    private void insertAfterSaleLogTable(String afterSaleId, OrderInfoDTO orderInfoDTO,
                                    Integer preAfterSaleStatus, Integer afterSaleStatus) {
        AfterSaleLogDO afterSaleLogDO = new AfterSaleLogDO();
        afterSaleLogDO.setAfterSaleId(afterSaleId);
        afterSaleLogDO.setPreStatus(preAfterSaleStatus);
        afterSaleLogDO.setCurrentStatus(afterSaleStatus);
        //  取消订单的业务值
        Integer cancelType = Integer.valueOf(orderInfoDTO.getCancelType());
        if (OrderCancelTypeEnum.USER_CANCELED.getCode().equals(cancelType)) {
            afterSaleLogDO.setRemark(OrderCancelTypeEnum.USER_CANCELED.getMsg());
        }else if (OrderCancelTypeEnum.TIMEOUT_CANCELED.getCode().equals(cancelType)) {
            afterSaleLogDO.setRemark(OrderCancelTypeEnum.TIMEOUT_CANCELED.getMsg());
        }
        log.info("新增售后单变更信息, 订单号:{},售后单号:{},状态:PreStatus{},CurrentStatus:{}", orderInfoDTO.getOrderId(),
                afterSaleId, afterSaleLogDO.getPreStatus(), afterSaleLogDO.getCurrentStatus());
        afterSaleLogDAO.save(afterSaleLogDO);
    }

    /**
     * 新增售后退款单表
     * @author xuyou
     * @date: 2022/6/29 15:00
     */
    private AfterSaleRefundDO insertAfterSaleRefundTable(String afterSaleId, OrderInfoDTO orderInfoDTO, Integer realRefundAmount) {
        String orderId = orderInfoDTO.getOrderId();

        AfterSaleRefundDO afterSaleRefundDO = new AfterSaleRefundDO();
        afterSaleRefundDO.setOrderId(orderId);
        afterSaleRefundDO.setAfterSaleId(afterSaleId);
        afterSaleRefundDO.setAccountType(AccountTypeEnum.THIRD.getCode());
        afterSaleRefundDO.setRefundStatus(RefundStatusEnum.UN_REFUND.getCode());
        afterSaleRefundDO.setRemark(RefundStatusEnum.UN_REFUND.getMsg());
        afterSaleRefundDO.setRefundAmount(realRefundAmount);
        afterSaleRefundDO.setAfterSaleBatchNo(orderId + RandomUtil.genRandomNumber(10));
        // 订单支付明细
        OrderPaymentDetailDO paymentDetail = orderPaymentDetailDAO.getPaymentDetailByOrderId(orderId);
        if (paymentDetail != null) {
            afterSaleRefundDO.setOutTradeNo(paymentDetail.getOutTradeNo());
            afterSaleRefundDO.setPayType(paymentDetail.getPayType());
        }
        afterSaleRefundDAO.save(afterSaleRefundDO);
        log.info("新增售后退款信息,订单号:{},售后单号:{},状态:{}", orderId, afterSaleId,
                afterSaleRefundDO.getRefundStatus());
        return afterSaleRefundDO;
    }


}
